<?php
	/*
	 * 	db_table_controller = new db_table_controller();
	 *  db_table_controller->set_table();
	 *  db_table_controller->set_fields();
	 */
	//------------------------------------------------------------------
	
	abstract class db_table_view{
		public function __construct($controller){
			$this->__controller = $controller;
		}
		
		public function __get($name){
			return $this->__controller->$name;
		}
		
		public function __call($name, $args){
			return call_user_func_array(array($this->__controller,$name),$args);
		}
		
		public function fetch_view(){
			
			$struct = $this->model->get_fields();
			$this->tpl->assign("WGT_TABLE_STRUCT",$struct);

			$this->tpl->assign("WGT_TABLE_KEY",$this->model->get_key());		
			$this->tpl->assign("WGT_TABLE_SSID",$this->__controller->ssid);
			
			$root = context::get("path")->get_root();
			$this->tpl->set_template_dir($root._DRS."resources"._DRS."widgets");
			
		}
	}
	
	class db_view_common extends db_table_view{
		public function fetch_view(){
			
			parent::fetch_view();
			
			$data = $this->model->fetch_data();
			$this->tpl->assign("WGT_TABLE_DATA",$data);
			$this->tpl->assign("WGT_TABLE_READONLY",$this->model->readonly);
			
			#print_r($this->__controller->controls);
			$this->tpl->assign("WGT_TABLE_CONTROLS",$this->__controller->controls);
			
			return $this->tpl->fetch("wgt_table_view.tpl");
		}
	}
	
	class db_view_edit extends db_table_view{
		public function fetch_view(){
			parent::fetch_view();
			
			$row_id = $this->get_row_id();
			$data = $this->model->fetch_row($row_id);
			$this->tpl->assign("WGT_TABLE_DATA",$data);
			
			return $this->tpl->fetch("wgt_table_edit.tpl");
		}
	}
	
	class db_view_add extends db_table_view{
		public function fetch_view(){
			
			parent::fetch_view();
			return $this->tpl->fetch("wgt_table_edit.tpl");
		}
	}
	
	
	
	class db_table_model {
		
		public $filters;
		public $readonly = false;
		
		private $page_limit;
		private $page;
		
		
		public function __construct(){
			$this->db = context::get("db");
			
			
			$this->fields = Array();
		}


		public function set_db($db){
			$this->db = $db;	//for the great justice
		}
		
		public function set_table($table_name){
			$this->table_name = $table_name;
		}
		
		public function set_page_limit($limit){
			$this->page_limit = $limit;
		}
		
		public function set_page($page){
			$this->page = $page;
		}
		
		public function add_field($field){
			$this->fields[] = $field;
		}
		
		public function get_fields(){
			//glue in key
			if ($this->key_id){
				$fields[] = array( "name"=>$this->key_id, "type"=>"label" );
			}
			
			foreach($this->fields as $field){
				$fields[] = $field;
			}
			
			return $fields;
		}
		
		public function set_key($key_id){
			$this->key_id = $key_id;
		}
		
		public function get_key(){
			return $this->key_id;
		}
		
		//TODO: refact me!
		private function __get_select(){
			
			foreach($this->fields as $__field){
				$select_fields[] = $__field["name"];
			}
			if($this->key_id){
				$select_fields[] = $this->key_id;
			}
			$select = implode(",", $select_fields);
			
			#-----------------------------------------------------------
			$from = $this->table_name;
			#-----------------------------------------------------------
			$_where = array();
			
			if ($this->filters){
				foreach ($this->filters as $key=>$val){
					#echo $val;
					$_where[] = "{$key} = ".context::get("db")->quote($val);

				}
			}
			
			$where = "";
			if (isset($_where) && sizeof($_where)){
				$where = implode(" AND ",$_where );
			}
			
			context::get("pagger")->set_db($this->db);
			context::get("pagger")->per_page = $this->page_limit;
			context::get("pagger")->page_id = $this->page;
			
			$query = context::get("pagger")->get_query($select,$from,$where);
			
			#context::get("io")->debug($query);
			#context::get("io")->dump($_where);

			return $query;

		}

		public function fetch_data(){
			$query = $this->__get_select();
			return $this->db->fetch_array($query);	
		}
		
		public function fetch_row($row_id){
			
			$this->filters[$this->key_id] = $row_id;	//set row filter;

			$query = $this->__get_select();
			#$query .= " WHERE {$this->key_id} = {$row_id} ";

			return $this->db->fetch_one($query);	
		}
	}
	
	//------------------------------------------------------------------

	class db_table_controller {
		
		private $view_poi;
		private $__cb = array();
		
		public $controls = array();
		
		public function __construct($table_name){
			$this->db = context::get("db");
			$this->tpl = context::get("tpl");
			$this->request = context::get("request");
			
			
			
			$this->model = new db_table_model();
			
			if($table_name){
				$this->ssid = md5($table_name);
				$this->set_table($table_name);
			}
			
			$this->set_key("id");	//by default
		}
		
		public function set_key($key_id){
			$this->model->set_key($key_id);
		}
		
		public function get_key(){
			return $this->model->get_key();
		}
		
		public function set_table($table){
			$this->model->set_table($table);
		}
		
		public function set_page_limit($limit){
			$this->model->set_page_limit($limit);
		}
		
		public function add_field($field){
			$this->model->add_field($field);
		}
		
		public function add_controll($control){
			$this->controls[] = $control;
		}
		
		
		public function add_fields($array){
			foreach($array as $field){
				$this->add_field($field);
			}
		}
		
		public function set_cb($name, $callback, $args = null){
			$this->__cb[$name] = array("cb"=>$callback,"args"=>$args);
		}
		
		
		public function set_actions($action_list){
			$this->action_list = $action_list;
	    }

		public function dispatch_action(){

			$ssid = $this->request->get_parameter("ssid","str");
			if ($ssid != $this->ssid){
				return;
			}

			$actions = array(
				"delete",
				"edit",
				"save",
				"add",
				"page"
			);
			
			$r_action = $this->request->get_parameter("db_action","str");
			
			foreach($actions as $action){
				if ($r_action == "__db_ctrl_".$action){

					//pre callback
					//--------------------------------------------------
					if (isset($this->__cb["pre_".$action])){
						$cb = $this->__cb["pre_".$action];
						if(is_callable($cb["cb"])){
							call_user_func_array($cb["cb"], $cb["args"]);
						}
					}
					//--------------------------------------------------
					
					//action
					call_user_func(array($this,"__dispatch_".$action));
					
					//post callback
					//--------------------------------------------------
					if ($this->__cb){
						$cb = $this->__cb[$action];
						if(is_callable($cb["cb"])){						
							call_user_func_array($cb["cb"], $cb["args"]);
						}
					}
					return true;
				}
			}
			
			foreach($this->controls as $control){
				if (!isset($control["action"])) {
					$control["action"] = $control["name"];
				}
				if (!isset($control["args"])) {
					$control["args"] = array();
				}
				
				
				
				if ($r_action == $control["action"]){
					if(is_callable($control["callback"])){
						call_user_func_array($control["callback"], $control["args"]);
					}
				}
			}
		}
		
		
		public function fetch_view(){

			if (!$this->view_poi){
				$this->view_poi = new db_view_common($this);
			}

			return $this->view_poi->fetch_view();
		}
		//--------------------------------------------------------------
		
		public function get_row_id(){
			return $this->request->get_parameter("row_id","int");
		}
	
		private function __dispatch_delete(){
			if ($row_id = $this->get_row_id()){
				$table =  $this->model->table_name;
				$key = 	  $this->get_key();
				
				if ($table && $key){
					$query = "DELETE FROM {$table} WHERE {$key} = {$row_id}";
					$this->db->query($query);
				}
			}
		}
		
		private function __dispatch_edit(){
			$this->view_poi = new db_view_edit($this);
		}
		
		private function __dispatch_add(){
			$this->view_poi = new db_view_add($this);
		}
		
		private function __dispatch_page(){
			$page = context::get("request")->get_param("pagger_page");
			$this->model->set_page($page);
		}
		
		private function __dispatch_save(){

			$fields = $this->model->get_fields();

			foreach ($fields as $field){
				switch($field["type"]){
					case "checkbox":
						$r_fields[$field["name"]] = (int)$this->request->get_parameter("__db_field_".$field["name"]);
					break;
					
					default:
						$r_fields[$field["name"]] = $this->request->get_parameter("__db_field_".$field["name"]);
					break;
				}
				
			}
			
			#print_r($r_fields);
			$key = 	  $this->get_key();
			
			$db_table_key = $r_fields[$key];
			
			if ((int)$db_table_key){
				#update entry
				
				$query = "UPDATE {$this->model->table_name} SET ";
				
				foreach ($r_fields as $field=>$val){
					if ($key != $field){
						$__tkn[] = " `{$field}` = ".context::get("db")->quote($val)." ";
					}
				}
				$query .= implode(",",$__tkn);
				$query .= " WHERE `{$key}` = {$r_fields[$key]}";
				
			
				context::get("db")->db_query($query);
				
			}else{
				
				$query = "INSERT INTO {$this->model->table_name} SET ";
				
				foreach ($r_fields as $field=>$val){
					if ($key != $field){
						$__tkn[] = " `{$field}` = ".context::get("db")->quote($val)." ";
					}
				}
				$query .= implode(",",$__tkn);
				
				context::get("db")->db_query($query);
			}
			
			
		}
		
		
	}
?>
